home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -seriously_amiga- / shareware / programming / c / vbcc / pasm / tables.c < prev    next >
C/C++ Source or Header  |  1998-01-05  |  9KB  |  329 lines

  1. /* $VER: pasm tables.c V0.5 (08.10.97)
  2.  *
  3.  * This file is part of pasm, a portable PowerPC assembler.
  4.  * Copyright (c) 1997  Frank Wille
  5.  *
  6.  * pasm is freeware and part of the portable and retargetable ANSI C
  7.  * compiler vbcc, copyright (c) 1995-97 by Volker Barthelmann.
  8.  * pasm may be freely redistributed as long as no modifications are
  9.  * made and nothing is charged for it. Non-commercial usage is allowed
  10.  * without any restrictions.
  11.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  12.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  13.  *
  14.  *
  15.  * v0.5 (08.10.97) phx
  16.  *      .globl directive declares unknown symbols in pass 1 as
  17.  *      externally defined. If the symbol is defined later in the
  18.  *      source, it will be made global by add_symbol().
  19.  * v0.3 (05.04.97) phx
  20.  *      Minor changes.
  21.  * v0.2 (25.03.97) phx
  22.  *      Writes ELF object for 32-bit PowerPC big-endian. Either absolute
  23.  *      or ELF output format may be selected. ELF is default for all
  24.  *      currently supported platforms. PPCasm supports nine different
  25.  *      relocation types (there are much more...).
  26.  *      Compiles and works also under NetBSD/amiga (68k).
  27.  *      Changed function declaration to 'new style' in all sources
  28.  *      (to avoid problems with '...' for example).
  29.  *      Externally defined symbols will automatically get global binding.
  30.  * v0.1 (11.03.97) phx
  31.  *      First test version with all PowerPC instructions and most
  32.  *      important directives. Only raw, absolute output.
  33.  * v0.0 (22.02.97) phx
  34.  *      File created.
  35.  */
  36.  
  37.  
  38. #define TABLES_C
  39. #include "ppcasm.h"
  40.  
  41.  
  42. void init_hashtables(struct GlobalVars *);
  43. void add_macro(struct GlobalVars *,struct Macro *);
  44. struct Symbol *add_symbol(struct GlobalVars *,char *,uint8,uint32);
  45. unsigned long elf_hash(unsigned char *);
  46. struct Symbol *search_symbol(struct GlobalVars *,char *);
  47. struct Section *search_section(struct GlobalVars *,char *);
  48. void search_opcode(struct GlobalVars *,struct ParsedLine *,char *,char *);
  49.  
  50. static void *alloc_hashtable(size_t);
  51. static void add_instruction(struct GlobalVars *,struct CPUInstr *);
  52. static void add_directive(struct GlobalVars *,struct Directive *);
  53. static struct CPUInstr *search_instr(struct GlobalVars *,char *);
  54. static struct Directive *search_directive(struct GlobalVars *,char *);
  55. static struct Macro *search_macro(struct GlobalVars *,char *);
  56. static void execute_macro(struct GlobalVars *,struct ParsedLine *);
  57. static void execute_directive(struct GlobalVars *,struct ParsedLine *);
  58.  
  59.  
  60.  
  61. void init_hashtables(struct GlobalVars *gv)
  62. {
  63.   struct CPUInstr *ins = instructions;
  64.   struct Directive *dir = directives;
  65.  
  66.   gv->symbols = alloc_hashtable(SYMHTABSIZE);
  67.   gv->instr = alloc_hashtable(INSTRHTABSIZE);
  68.   gv->directives = alloc_hashtable(DIRHTABSIZE);
  69.   gv->macros = alloc_hashtable(MACROHTABSIZE);
  70.   while (ins->name)
  71.     add_instruction(gv,ins++);
  72.   while (dir->name)
  73.     add_directive(gv,dir++);
  74. }
  75.  
  76.  
  77. static void *alloc_hashtable(size_t entries)
  78. {
  79.   return (alloczero(entries * sizeof(void *)));
  80. }
  81.  
  82.  
  83. static void add_instruction(struct GlobalVars *gv,struct CPUInstr *ins)
  84. /* make new entry into instruction hash table */
  85. {
  86.   struct CPUInstr *chain;
  87.   unsigned long offs = elf_hash(ins->name)%INSTRHTABSIZE;
  88.  
  89.   if (!(ins->flags & F_EXTENDED) || !gv->noextmnemo) {
  90.     if (chain = gv->instr[offs])
  91.       ins->hash_chain = chain;
  92.     else
  93.       ins->hash_chain = NULL;
  94.     gv->instr[offs] = ins;
  95.   }
  96. }
  97.  
  98.  
  99. static void add_directive(struct GlobalVars *gv,struct Directive *dir)
  100. /* make new entry into directive hash table */
  101. {
  102.   struct Directive *chain;
  103.   unsigned long offs = elf_hash(dir->name)%DIRHTABSIZE;
  104.  
  105.   if (chain = gv->directives[offs])
  106.     dir->hash_chain = chain;
  107.   else
  108.     dir->hash_chain = NULL;
  109.   gv->directives[offs] = dir;
  110. }
  111.  
  112.  
  113. void add_macro(struct GlobalVars *gv,struct Macro *mac)
  114. /* make new entry into macro hash table */
  115. {
  116.   struct Macro *chain,*m;
  117.   unsigned long offs = elf_hash(mac->name)%MACROHTABSIZE;
  118.  
  119.   if (chain = m = gv->macros[offs]) {  /* hash code already used? */
  120.     do {
  121.       if (!strcmp(m->name,mac->name)) {
  122.         error(8,mac->name);  /* macro defined twice! */
  123.         break;
  124.       }
  125.     }
  126.     while (m = m->hash_chain);
  127.   }
  128.   gv->macros[offs] = mac;
  129.   mac->hash_chain = chain;
  130. }
  131.  
  132.  
  133. struct Symbol *add_symbol(struct GlobalVars *gv,char *name,uint8 type,
  134.                           uint32 value)
  135. /* define new symbol - absolute, relocatable or external */
  136. {
  137.   struct Symbol *sym,*chain;
  138.   unsigned long offs = elf_hash(name)%SYMHTABSIZE;
  139.  
  140.   if (chain = sym = gv->symbols[offs]) {  /* hash code already used? */
  141.     do {
  142.       if (!strcmp(name,sym->name)) {
  143.         if (sym->type == SYM_EXTERN) {  /* declared external by .globl? */
  144.           if ((sym->type = type) == SYM_RELOC)
  145.             sym->relsect = gv->csect;
  146.           sym->value = value;
  147.         }
  148.         else
  149.           error(7,name);  /* symbol defined twice! */
  150.         return (sym);
  151.       }
  152.     }
  153.     while (sym = sym->hash_chain);
  154.   }
  155.   gv->symbols[offs] = sym = alloczero(sizeof(struct Symbol));
  156.   sym->hash_chain = chain;
  157.   sym->name = allocstring(name);
  158.   sym->value = value;
  159.   if ((sym->type = type) == SYM_RELOC)
  160.     sym->relsect = gv->csect;
  161.   else if (type == SYM_EXTERN)
  162.     sym->bind = SYMB_GLOBAL;
  163.   return (sym);
  164. }
  165.  
  166.  
  167. unsigned long elf_hash(unsigned char *name)
  168. /* calculate a hash code as used in ELF objects */
  169. {
  170.   unsigned long h=0,g;
  171.  
  172.   while (*name) {
  173.     h = (h << 4) + *name++;
  174.     if (g = h & 0xf0000000)
  175.       h ^= g >> 24;
  176.     h &= ~g;
  177.   }
  178.   return (h);
  179. }
  180.  
  181.  
  182. struct Symbol *search_symbol(struct GlobalVars *gv,char *name)
  183. /* find a symbol in the symbol hash table */
  184. {
  185.   struct Symbol *chain;
  186.   unsigned long offs = elf_hash(name)%SYMHTABSIZE;
  187.  
  188.   chain = gv->symbols[offs];
  189.   while (chain) {
  190.     if (!strcmp(chain->name,name))
  191.       return (chain);
  192.     chain = chain->hash_chain;
  193.   }
  194.   return (NULL);
  195. }
  196.  
  197.  
  198. static struct CPUInstr *search_instr(struct GlobalVars *gv,char *name)
  199. /* find an instruction in the instruction hash table */
  200. {
  201.   struct CPUInstr *chain;
  202.   unsigned long offs = elf_hash(name)%INSTRHTABSIZE;
  203.  
  204.   chain = gv->instr[offs];
  205.   while (chain) {
  206.     if (!strcmp(chain->name,name))
  207.       return (chain);
  208.     chain = chain->hash_chain;
  209.   }
  210.   return (NULL);
  211. }
  212.  
  213.  
  214. static struct Directive *search_directive(struct GlobalVars *gv,char *name)
  215. /* find a directive in the directive hash table */
  216. {
  217.   struct Directive *chain;
  218.   unsigned long offs = elf_hash(name)%DIRHTABSIZE;
  219.  
  220.   chain = gv->directives[offs];
  221.   while (chain) {
  222.     if (!strcmp(chain->name,name))
  223.       return (chain);
  224.     chain = chain->hash_chain;
  225.   }
  226.   return (NULL);
  227. }
  228.  
  229.  
  230. static struct Macro *search_macro(struct GlobalVars *gv,char *name)
  231. /* find a macro in the macro hash table */
  232. {
  233.   struct Macro *chain;
  234.   unsigned long offs = elf_hash(name)%MACROHTABSIZE;
  235.  
  236.   chain = gv->macros[offs];
  237.   while (chain) {
  238.     if (!strcmp(chain->name,name))
  239.       return (chain);
  240.     chain = chain->hash_chain;
  241.   }
  242.   return (NULL);
  243. }
  244.  
  245.  
  246. struct Section *search_section(struct GlobalVars *gv,char *name)
  247. {
  248.   struct Section *nextsec,*sec=(struct Section *)gv->sectionlist.first;
  249.  
  250.   while (nextsec = (struct Section *)sec->n.next) {
  251.     if (!strcmp(name,sec->name))
  252.       return (sec);
  253.     sec = nextsec;
  254.   }
  255.   return (NULL);
  256. }
  257.  
  258.  
  259. void search_opcode(struct GlobalVars *gv,struct ParsedLine *pl,
  260.                    char *opname,char *operand)
  261. {
  262.   if (gv->alignflag)
  263.     pl->flags |= PLF_ALIGN;
  264.   gv->alignflag = FALSE;
  265.   if (pl->opcode = (void *)search_macro(gv,opname)) {
  266.     pl->type = OT_MACRO;
  267.     pl->operand = operand;
  268.     execute_macro(gv,pl);
  269.   }
  270.   else if (pl->opcode = (void *)search_instr(gv,opname)) {
  271.     pl->type = OT_INSTRUCTION;
  272.     pl->operand = allocstring(operand);
  273.     gv->csect->pc += 4;  /* every PPC instruction has a size of 4 bytes */
  274.   }
  275.   else if (pl->opcode = (void *)search_directive(gv,opname)) {
  276.     pl->type = OT_DIRECTIVE;
  277.     pl->operand = allocstring(operand);
  278.     execute_directive(gv,pl);
  279.   }
  280.   else if (pl->opcode = (void *)search_section(gv,opname)) {
  281.     pl->type = OT_SECTION;
  282.     activate_section(gv,(struct Section *)pl->opcode);
  283.   }
  284.   else
  285.     error(10,opname);  /* Unknown opcode */
  286. }
  287.  
  288.  
  289. static void execute_macro(struct GlobalVars *gv,struct ParsedLine *pl)
  290. /* creates a SourceText structure for every macro invocation, parses */
  291. /* macro parameters and recursively calls pass1() to execute the macro */
  292. {
  293.   struct Macro *m = (struct Macro *)pl->opcode;
  294.   struct MacroParams *mp = alloczero(sizeof(struct MacroParams));
  295.   struct SourceText *stxt = alloc(sizeof(struct SourceText));
  296.   char *mac_params = alloc(strlen(pl->operand)+1);
  297.   uint32 oldnarg = gv->nargsym->value;
  298.  
  299.   /* create SourceText node for macro-call */
  300.   stxt->name = m->name;
  301.   stxt->text = m->text;
  302.   stxt->nlines = m->nlines;
  303.   stxt->plin = alloczero(m->nlines * sizeof(struct ParsedLine));
  304.   addtail(&gv->sourcelist,&stxt->n);
  305.  
  306.   /* initialize MacroParams structure */
  307.   mp->call_id = gv->macrocnt++;
  308.   strcpy(mac_params,pl->operand);
  309.   read_macro_params(gv,pl,mp,mac_params);
  310.   pl->narg = (uint8)mp->narg;
  311.   gv->nargsym->value = mp->narg;
  312.  
  313.   /* recursively call pass 1 and create new SourceThread */
  314.   pass1(gv,stxt,mp,gv->cthread);
  315.   gv->nargsym->value = oldnarg;
  316.  
  317.   /* cleanup */
  318.   free(mp);
  319.   pl->opcode = stxt;
  320. }
  321.  
  322.  
  323. static void execute_directive(struct GlobalVars *gv,struct ParsedLine *pl)
  324. {
  325.   struct Directive *d = (struct Directive *)pl->opcode;
  326.  
  327.   (d->dfunct)(gv,pl);
  328. }
  329.